package leetcode;

import java.util.ArrayList;
import java.util.List;

/**
 * 89. 格雷编码
 * n 位格雷码序列 是一个由 2n 个整数组成的序列，其中：
 * 每个整数都在范围 [0, 2n - 1] 内（含 0 和 2n - 1）
 * 第一个整数是 0
 * 一个整数在序列中出现 不超过一次
 * 每对 相邻 整数的二进制表示 恰好一位不同 ，且
 * 第一个 和 最后一个 整数的二进制表示 恰好一位不同
 * 给你一个整数 n ，返回任一有效的 n 位格雷码序列 。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：n = 2
 * 输出：[0,1,3,2]
 * 解释：
 * [0,1,3,2] 的二进制表示是 [00,01,11,10] 。
 * - 00 和 01 有一位不同
 * - 01 和 11 有一位不同
 * - 11 和 10 有一位不同
 * - 10 和 00 有一位不同
 * [0,2,3,1] 也是一个有效的格雷码序列，其二进制表示是 [00,10,11,01] 。
 * - 00 和 10 有一位不同
 * - 10 和 11 有一位不同
 * - 11 和 01 有一位不同
 * - 01 和 00 有一位不同
 * 示例 2：
 * <p>
 * 输入：n = 1
 * 输出：[0,1]
 */
public class GrayCode {

    /**
     * 背就行
     * <p>
     * G(n) 为 n 的格雷编码，R(n) 为 G(n) 翻转
     * G(n+1) = G(n) + R(n)
     * <p>
     * 2 格雷编码为 00 01 11 10，翻转 10 11 01 00，3的各类编码为 正序前面加0 倒序前面加1 ： 000 001 011 010 110 111 101 100
     *
     * @param n
     * @return
     */
    // 没看懂
    public List<Integer> grayCode(int n) {
        List<Integer> res = new ArrayList<Integer>();
        // 先把0加上
        res.add(0);
        int head = 1;
        // 处理n次
        for (int i = 0; i < n; i++) {

            for (int j = res.size() - 1; j >= 0; j--) {
                res.add(head + res.get(j));
            }

            head <<= 1;
        }
        return res;

    }

}
